home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / ham / vhfprp11.zip / VHFPROP.C < prev    next >
C/C++ Source or Header  |  1994-09-26  |  16KB  |  491 lines

  1. /* A computer program to predict VHF propogation */
  2. /* This program has been placed in the Public Domain by its author - K2LMG */
  3. /* Compile under TURBO-C -- The author used BCC Version 2.0 */
  4. /* History:449 */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <conio.h>
  10. #include <dos.h>
  11. #include <math.h>
  12.  
  13. #define TRUE        1
  14. #define FALSE        0
  15. #define FADE_VALUE    7
  16. #define VERSION        "1.1"
  17.  
  18. /* 6m data, 0.5 64.3, 1 70.3, 5 118, 10 131, 20 144.5, 30 154, 40 161, 50
  19.         169, 75 174, 100 177.5, 150 183.5, 200 188, 250 194, 300 207, 350 214,
  20.         400 222, 450 229, 500 235, 550 242 */
  21.  
  22. double coef6m[] = {-1.484302997616194e-21, 4.1038152183463572e-18,
  23.         -4.8551992957369198e-15, 3.2101311680399517e-12,
  24.         -1.2996161086602211e-09, 3.3199292557524471e-07,
  25.         -5.3228661204510353e-05, 0.0051731206040884119, -0.28532370451114214,
  26.         8.1911236469791699, 67.635788039642023};
  27.  
  28. /* 2m data -- 0.5 73.9, 1 79.5, 5 93.9 10 131, 20 146, 30 157, 40 167, 50
  29.         170, 75 174, 100 178, 150 184, 200 188.5, 250 194, 300 206.5, 350 214,
  30.         400 222, 450 228, 500 234, 550 241 */
  31.  
  32. double coef2m[] = {-1.0140612223930305e-21, 2.8210504968786972e-18,
  33.         -3.3639226709952115e-15, 2.2467324291152165e-12,
  34.         -9.2161956771287313e-10, 2.3956384975135559e-07,
  35.         -3.9329897909964029e-05, 0.0039527147149096397, -0.22900560651309843,
  36.         7.0593776226319154, 76.297125007618945};
  37.  
  38. /* 1.25m data, 0.5 77.5, 1 83.5, 5 119, 10 132, 20 148, 30 160, 40 168, 50
  39.         171, 75 175.5, 100 180, 150 186.5, 200 191, 250 197, 300 209, 350
  40.         216.5, 400 224, 450 230, 500 236.5, 550 242 */
  41.  
  42. double coef125cm[] = {-9.3022498752972239e-22, 2.5942502213057621e-18,
  43.         -3.1027271861262425e-15, 2.079688661769463e-12,
  44.         -8.5672949008653612e-10, 2.2382801286343053e-07,
  45.         -3.6971168328522354e-05, 0.0037433231319706261, -0.21886313655344825,
  46.         6.8335531497848931, 79.398990370051834};
  47.  
  48. /* 70cm data -- 432 Mhz 0.5 83.4, 1 89.5, 5 103.4 10 132, 20 150, 30 163.5, 40
  49.         170, 50 173, 75 178, 100 183, 150 190, 200 196, 250 202, 300 213, 350
  50.         220.5, 400 228, 450 234, 500 240, 550 246 */
  51.  
  52. double coef70cm[] = {-4.5865358353610324e-22, 1.3108230411727579e-18,
  53.         -1.6135046051301692e-15, 1.1190620728434546e-12,
  54.         -4.8033074993680223e-10, 1.319708437884491e-07,
  55.         -2.3222247971860489e-05, 0.0025516659663546628, -0.1661238781990346,
  56.         5.9666161768039707, 81.595953373755762};
  57.  
  58. /* 33cm data, 0.5 89.7, 1 95.7, 5 119.5, 10 133, 20 153.5, 30 168.5, 40
  59.         173.5, 50 177, 75 183.5, 100 189, 150 197, 200 202.5, 250 209, 300
  60.         221.5, 350 228, 400 236, 450 241.5, 500 248, 550 251 */
  61.  
  62. double coef33cm[] = {-5.2781673891878704e-22, 1.4951138952704982e-18,
  63.         -1.8211439179439397e-15, 1.2472237245268508e-12,
  64.         -5.2709664954563149e-10, 1.4203323864028798e-07,
  65.         -2.4385939877300226e-05, 0.0025983803016192764, -0.16327178023671626,
  66.         5.7118712681798156, 89.957616754542244};
  67.  
  68. /* 23cm data -- 0.5 92.8, 1 98.9, 5 120, 10 134, 20 157, 30 171.5, 40 178,
  69.         50 182, 75 188.5, 100 195, 150 203.5, 200 210, 250 216, 300 228, 350
  70.         234, 400 243, 450 248, 500 254, 550 257 */
  71.  
  72. double coef23cm[] = {-4.324473300406565e-22, 1.2258059596030557e-18,
  73.         -1.4960261442115287e-15, 1.0285157566223974e-12,
  74.         -4.3756476216365891e-10, 1.1917818401558418e-07,
  75.         -2.0805095457433704e-05, 0.002273429714275005, -0.14832922840239154,
  76.         5.4937966328715673, 92.663217031298927};
  77.  
  78. /* Fade data -- Fading data 0.5 0, 5 0, 10 3, 20 5, 30 7, 40 9, 50 11.5, 60
  79.         14.5, 70 16.5, 80 17.5, 90 18, 100 18, 110 17.5, 120 17, 130 16.5, 140
  80.         15.5, 150 14.5, 160 13.5, 170 12.5, 180 11.5, 190 10, 200 9.5, 250 8.5,
  81.         300 8, 350 7.5, 400 7, 450 7, 500 7 */
  82.  
  83. double coeffade[] = {-1.931900179565423e-22, 4.7890688047850891e-19,
  84.         -5.0385411769900302e-16, 2.9177755838734291e-13,
  85.         -1.0055284586681718e-10, 2.0690926814195451e-08,
  86.         -2.3867831104375384e-06, 0.00013095435698746912, -0.003263676118036522,
  87.         0.27959303349242731, -0.376155914778245};
  88.  
  89. double coefheight[] = {1.15144e-08, -3.48166e-06, 4.34947e-04, -2.98883e-02,
  90.     1.20410e+00, -1.84529e+01};
  91.  
  92. double poly_value(double dist, double coeff[], int degree)
  93. { double term;
  94.   int i;
  95.   term = coeff[0];
  96.   for (i = 1; i <= degree; i++)
  97.       term = term * dist + coeff[i];
  98.   return term;
  99. }
  100.  
  101. double path_loss_func(double dist, int freq_index)
  102. { double ret;
  103.   if (dist < 1.0) dist = 1.0;
  104.   switch (freq_index)
  105.     { case 0: ret = poly_value(dist, coef6m, 10);
  106.           break;
  107.       case 1: ret = poly_value(dist, coef2m, 10);
  108.           break;
  109.       case 2: ret = poly_value(dist, coef125cm, 10);
  110.           break;
  111.       case 3: ret = poly_value(dist, coef70cm, 10);
  112.           break;
  113.       case 4: ret = poly_value(dist, coef33cm, 10);
  114.           break;
  115.       case 5: ret = poly_value(dist, coef23cm, 10);
  116.           break;
  117.     }
  118.   return ret;
  119. }
  120.  
  121. double fade_func(double dist)
  122. { if (dist < 0.5 ) dist = 0.5;
  123.   return poly_value(dist, coeffade, 10);
  124. }
  125.  
  126. double height_gain(double height)
  127. { if (height > 100) return 8.0;
  128.   if (height < 0) return -7.0;
  129.   return poly_value(height, coefheight, 5);
  130. }
  131.  
  132. void beep(void)
  133. { printf("%c",7);            /* Beep */
  134. }
  135.  
  136. /* trans array: power, distance, antenna_gain, antenna_height,
  137.     site_height, line_loss, site_angle
  138.  * rec array:   modulation_loss, noise_figure, antenna_gain, antenna_height,
  139.     site_height, line_loss, site_angle, bandwidth, band, dummy;
  140.  */
  141.  
  142. void main()
  143. { char ch, input[20];
  144.   int i, key, row, col, stop, index, mod_index, reliability, band_index,
  145.     fading, key_save;
  146.   double value;
  147.   double transmit[] = {50,10,0,0,0,0,0};
  148.   double receiver[] = {7,1,0,0,0,0,0,5,1,0};
  149.   double distance, hor_dist, dist_lineof_sight, signal2noise, station_gain,
  150.     path_loss, rec_sensitivity, h_gain_trans, h_gain_rec;
  151.   int next_row_left_down[] = {0,0,0,5,5,6,7,8,9,10,13,13,13,5,5,5,5,5,5};
  152.   int next_row_left_up[] = {0,0,0,13,13,13,5,6,7,8,9,10,10,10,13,13,13,13,13,13};    /* this has row 17 defined */
  153.   int next_row_right_down[] = {0,0,0,5,5,6,7,8,9,10,11,15,15,15,15,16,17,18,5};
  154.   int next_row_right_up[] = {0,0,0,18,18,18,5,6,7,8,9,10,11,11,11,11,15,16,17};
  155.   char *mod_mode[] = {"fm","ssb","cw","am"};
  156.   double mod_value[] = {7,3,0,7};
  157.   char *reliab_mode[] = {"50%","99%"};
  158.   char *fade_mode[] = {"No","Yes"};
  159.   char *band[] = {"6m","2m","1.25m","70cm","33cm","23cm"};
  160.   double band_value[] = {50,146,222,440,902,1280};
  161.  
  162.   row = 13;                    /* cursor starting position */
  163.   col = 30;
  164.   band_index = reliability = fading = 1;
  165.   mod_index = 0;
  166.   key_save = 0;
  167.  
  168.   clrscr();
  169.   gotoxy(7,1); printf("VHFProp -- An interactive Signal Analysis Program -- Version %s",VERSION);
  170.   gotoxy(5,3); printf("Transmitting Station Parameters");
  171.   gotoxy(40,3); printf("%c",179);
  172.   gotoxy(45,3); printf("Receiving Station Parameters");
  173.   gotoxy(65,24); printf("Use ESC to Quit");
  174.   gotoxy(1,4);
  175.   for (i=2; i<79; i++)
  176.      printf("%c",196);
  177.   gotoxy(40,4); printf("%c",197);
  178.   for (i=5; i<12; i++)            /* draw vertical bar */
  179.     { gotoxy(40,i);
  180.       printf("%c",179);
  181.     }
  182.   gotoxy(42,14);            /* underline Modes */
  183.   for (i=0; i<34; i++)
  184.      printf("%c",196);
  185.  
  186.   gotoxy(14,18);
  187.   printf("Results");
  188.   gotoxy(2,19);                /* underline Results */
  189.   for (i=0; i<35; i++)
  190.      printf("%c",196);
  191.  
  192.   for(;;)
  193.    { _setcursortype(_NOCURSOR);
  194.      gotoxy(2,5);
  195.      printf("Power (watts):");
  196.      gotoxy(30,5);
  197.      printf("%7.1lf",transmit[0]);
  198.      gotoxy(42,5);
  199.      printf("Noise Figure (db):");
  200.      gotoxy(69,5);
  201.      printf("%7.1lf\n",receiver[1]);
  202.      gotoxy(2,6);
  203.      printf("Line Loss (db):");
  204.      gotoxy(30,6);
  205.      printf("%7.1lf",transmit[5]);
  206.      gotoxy(42,6);
  207.      printf("Line Loss (db): ");
  208.      gotoxy(69,6);
  209.      printf("%7.1lf\n",receiver[5]);
  210.      gotoxy(2,7);
  211.      printf("Antenna Gain (db): ");
  212.      gotoxy(30,7);
  213.      printf("%7.1lf",transmit[2]);
  214.      gotoxy(42,7);
  215.      printf("Antenna Gain (db): ");
  216.      gotoxy(69,7);
  217.      printf("%7.1lf\n",receiver[2]);
  218.      gotoxy(2,8);
  219.      printf("Antenna Height (feet): ");
  220.      gotoxy(30,8);
  221.      printf("%7.1lf",transmit[3]);
  222.      gotoxy(42,8);
  223.      printf("Antenna Height (feet): ");
  224.      gotoxy(69,8);
  225.      printf("%7.1lf\n",receiver[3]);
  226.      gotoxy(2,9);
  227.      printf("Site Height (feet): ");
  228.      gotoxy(30,9);
  229.      printf("%7.1lf",transmit[4]);
  230.      gotoxy(42,9);
  231.      printf("Site Height (feet): ");
  232.      gotoxy(69,9);
  233.      printf("%7.1lf",receiver[4]);
  234.      gotoxy(2,10);
  235.      printf("Horizon Angle (degrees): ");
  236.      gotoxy(30,10);
  237.      printf("%7.1lf",transmit[6]);
  238.      gotoxy(42,10);
  239.      printf("Horizon Angle (degrees): ");
  240.      gotoxy(69,10);
  241.      printf("%7.1lf",receiver[6]);
  242.      gotoxy(42,11);
  243.      printf("Bandwidth (KHz):");
  244.      gotoxy(69,11);
  245.      printf("%7.1lf\n",receiver[7]);
  246.      gotoxy(2,13);
  247.      printf("Distance (miles): ");
  248.      gotoxy(30,13);
  249.      printf("%7.1lf",transmit[1]);
  250.      gotoxy(42,13);
  251.      printf("  Modes - Select with Enter Key");
  252.      gotoxy(42,15);
  253.      printf("Frequency Band: ");
  254.      gotoxy(69,15);
  255.      printf("%7s",band[band_index]);
  256.      gotoxy(42,16);
  257.      printf("Modulation: ");
  258.      gotoxy(69,16);
  259.      printf("%7s",mod_mode[mod_index]);
  260.      gotoxy(42,17);
  261.      printf("Reliability: ");
  262.      gotoxy(69,17);
  263.      printf("%7s",reliab_mode[reliability]);
  264.      gotoxy(42,18);
  265.      printf("Include Fading: ");
  266.      gotoxy(69,18);
  267.      printf("%7s",fade_mode[fading]);
  268.  
  269.      _setcursortype(_NORMALCURSOR);
  270.      gotoxy(col,row);
  271.      stop = FALSE;
  272.  
  273.        /* Change the parameters
  274.     * key_save remembers the input termination key.  If it is an arrow
  275.     * go in the specified direction.
  276.     */
  277.      do
  278.        { if (!key_save)
  279.            { _AH = 0;
  280.              geninterrupt(0x16);
  281.              key = _AX;
  282.          ch = key & 0xff;
  283.              if (ch != 0 && (isdigit(ch) || ch == '\r')) stop = TRUE;
  284.        }
  285.      key_save = 0;
  286.          switch (key)
  287.           { case 0x4800: if (col > 40) row = next_row_right_up[row];
  288.                 else row = next_row_left_up[row];
  289.               gotoxy(col,row);
  290.                          break;
  291.             case 0x5000: if (row < 19)
  292.                  { if (col > 40) row = next_row_right_down[row];
  293.                       else row = next_row_left_down[row];
  294.                  }
  295.               gotoxy(col,row);
  296.                   break;
  297.          case 0x4b00: if (col == 69) col = 30;
  298.               row = next_row_left_up[row+1];
  299.               gotoxy(col,row);
  300.                   break;
  301.          case 0x4d00: if (col == 30) col = 69;
  302.               row = next_row_right_up[row+1];
  303.               gotoxy(col,row);
  304.                   break;
  305.              case 0x1c0d: if (row == 15)
  306.                 { if (band_index < 5 )band_index++;
  307.                   else band_index = 0;
  308.                 }
  309.                 else
  310.                  if (row == 16)
  311.                    { if (mod_index < 3 )mod_index++;
  312.                     else mod_index = 0;
  313.                    }
  314.                    else
  315.                      if (row == 17) reliability ^= 1;
  316.                         else
  317.                       if (row == 18) fading ^= 1;
  318.                             else stop = FALSE;
  319.               key = 0;
  320.                   break;
  321.              case 0x11b:  gotoxy(22,25);
  322.                   printf("Thank you for using VHFProp -- de K2LMG");
  323.                   exit(0);
  324.            }
  325.        }  while (!stop);
  326.  
  327.      input[0] = key & 0x0ff;
  328.      if (key > 0)
  329.        { printf("%c         \b\b\b\b\b\b\b\b\b",input[0]);    /* clear the previous value */
  330.          i = 1;
  331.          do
  332.            { _AH = 0;
  333.              geninterrupt(0x16);
  334.              key = _AX;
  335.          ch = key & 0x0ff;
  336.              if (ch == 0) break;
  337.              if (ch == '\b')
  338.                { if (i > 0)
  339.                    { i--;
  340.                     printf("\b \b");            /* do editing the hard way */
  341.                   }
  342.               }
  343.               else if ((isdigit(ch) || ch == '.') && i < 8)
  344.               { printf("%c",ch);
  345.             input[i++] = ch;
  346.               }
  347.            } while (ch != '\r');
  348.         input[i] = '\0';
  349.      }
  350.  
  351.      key_save = key & 0xff00;            /* last key input */
  352.      value = strtod(input,NULL);
  353.      if (col < 42)                /* set index to store value in correct array element */
  354.        { switch (row)
  355.           { case 5: index = 0;
  356.                    break;
  357.             case 6: index = 5;
  358.                    break;
  359.             case 7: index = 2;
  360.                    break;
  361.             case 8: index = 3;
  362.                    break;
  363.             case 9: index = 4;
  364.                        break;
  365.            case 10: index = 6;
  366.                        break;
  367.            case 13: index = 1;
  368.                         break;
  369.           }
  370.          transmit[index] = value;
  371.       }
  372.        else
  373.         { switch (row)
  374.            { case 5: index = 1;
  375.                     break;
  376.              case 6: index = 5;
  377.                     break;
  378.              case 7: index = 2;
  379.                     break;
  380.              case 8: index = 3;
  381.                     break;
  382.              case 9: index = 4;
  383.                         break;
  384.             case 10: index = 6;
  385.                         break;
  386.             case 11: index = 7;
  387.                         break;
  388.             case 15: index = 8;
  389.              value = band_value[band_index];
  390.                         break;
  391.             case 16: index = 0;
  392.              value = mod_value[mod_index];
  393.                         break;
  394.             case 17: index = 9;
  395.             case 18: index = 9;            /* 8 is when result not saved */
  396.                         break;
  397.            }
  398.          receiver[index] = value;
  399.       }
  400.  
  401.      distance = transmit[1];
  402.      hor_dist = (transmit[6] + receiver[6]) * 69.0;
  403.  
  404.   /* look for values which could give problems */
  405.      if (distance > 500)
  406.        { beep();
  407.          distance = transmit[1] = 500.0;
  408.        }
  409.      if (distance + hor_dist <= 0.0 || distance + hor_dist > 500.0)
  410.        { if (col < 42) transmit[6] = 0.0;
  411.        else receiver[6] = 0.0;
  412.      beep();
  413.      hor_dist = 0.0;
  414.        }
  415.      distance += hor_dist;
  416.      if (distance > 500)
  417.        { beep();
  418.          distance = 500.0;
  419.        }
  420.      if (transmit[0] < 0.01)                    /* power */
  421.        { transmit[0] = 0.01;
  422.      beep();
  423.        }
  424.      if (transmit[3] < 0)                    /* antenna height */
  425.        { transmit[3] = 0.0;
  426.      beep();
  427.        }
  428.      if (receiver[3] < 0)
  429.        { receiver[3] = 0.0;
  430.      beep();
  431.        }
  432.      if (transmit[4] < 0)                    /* site height */
  433.        { transmit[4] = 0.0;
  434.      beep();
  435.        }
  436.      if (receiver[4] < 0)
  437.        { receiver[4] = 0.0;
  438.      beep();
  439.        }
  440.  
  441.      dist_lineof_sight = 1.225 * (sqrt(transmit[4]) + sqrt(receiver[4]));
  442.      if (dist_lineof_sight * 1.075 < distance)        /* when divisor -> distance - dist_lineof_sight <- is too small error occur */
  443.        { path_loss = path_loss_func(distance - dist_lineof_sight, band_index);
  444.          path_loss += 20 * log10(distance/(distance - dist_lineof_sight));
  445.        }
  446.        else
  447.          { path_loss = 36.6 + 20.0*log10(distance) + 20.0*log10(receiver[8]);
  448.        dist_lineof_sight = distance;
  449.      }
  450.      if (reliability) path_loss += fade_func(distance - dist_lineof_sight);
  451.      rec_sensitivity = 10 * log10(pow(10, receiver[1]/10) * receiver[7] /
  452.                2.188e17) + receiver[5];        /* as per QST article include line_loss here */
  453.      h_gain_trans = height_gain(transmit[3]);
  454.      h_gain_rec = height_gain(receiver[3]);
  455.      station_gain = 10 * log10(transmit[0]) + h_gain_trans + transmit[2]
  456.                + h_gain_rec + receiver[2] - transmit[5]
  457.             - receiver[0] - rec_sensitivity;
  458.      if (fading) station_gain -= FADE_VALUE * (distance - dist_lineof_sight)
  459.                 / distance;
  460.      signal2noise = station_gain - path_loss;
  461.  
  462.      _setcursortype(_NOCURSOR);
  463.      gotoxy(2,15);
  464.      printf("Line of sight distance:");
  465.      gotoxy(30,15);
  466.      printf("%7.1lf",dist_lineof_sight);
  467.      gotoxy(2,16);
  468.      printf("Eff. scatter distance:");
  469.      gotoxy(30,16);
  470.      printf("%7.1lf",distance - dist_lineof_sight);
  471.  
  472.      gotoxy(2,20);
  473.      printf("Signal to Noise Ratio (db):");
  474.      gotoxy(30,20);
  475.      printf("%7.1lf",signal2noise);
  476.      gotoxy(2,21);
  477.      printf("Path Loss (db):");
  478.      gotoxy(30,21);
  479.      printf("%7.1lf",path_loss);
  480.      gotoxy(2,22);
  481.      printf("Receiver Sensitivity (db):");
  482.      gotoxy(30,22);
  483.      printf("%7.1lf",rec_sensitivity);
  484.      gotoxy(2,23);
  485.      printf("Station Gain (db):");
  486.      gotoxy(30,23);
  487.      printf("%7.1lf\n",station_gain);
  488.      _setcursortype(_NORMALCURSOR);
  489.    }
  490. }
  491.